package com.ngsky.ana.server;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.awt.*;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.*;

/**
 * @Author syx
 * @Desc
 * @Create 2020/6/15 13:14
 */
public class AnalyzeServer {
    public final static int COLOR_SIZE = 10;

    // 黑色
    private final static int BLACK = 0;
    // 灰色
    private final static int GRAY = 1;
    // 白色
    private final static int WHITE = 2;
    // 红色
    private final static int RED = 3;
    // 橙色
    private final static int ORANGE = 4;
    // 黄色
    private final static int YELLOW = 5;
    // 绿色
    private final static int GREEN = 6;
    // 青色
    private final static int CYAN = 7;
    // 蓝色
    private final static int BLUE = 8;
    // 紫色
    private final static int PURPLE = 9;

    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        //注意程序运行的时候需要在VM option添加该行 指明opencv的dll文件所在路径
        //-Djava.library.path=$PROJECT_DIR$\opencv\x64
    }

    public double[] analyze(String fileName) {
        if (null == fileName || "".equals(fileName)) {
            return null;
        }
        Mat mat = Imgcodecs.imread(fileName);

        Mat hsvImg = new Mat(mat.size(), mat.type());
        Imgproc.cvtColor(mat, hsvImg, Imgproc.COLOR_RGB2HSV_FULL);

        // 色调（H），饱和度（S），明度（V)
        int num_rows = hsvImg.rows();
        int num_col = hsvImg.cols();

        double[] color = new double[COLOR_SIZE];

        for (int i = 0; i < num_rows; i++) {
            for (int j = 0; j < num_col; j++) {
                // 获取每个像素
                double[] clone = hsvImg.get(i, j).clone();
                int co = who(clone[0], clone[1], clone[2]);
                if (-1 != co) {
                    color[co] += 1;
                }
            }
        }

        double count = num_rows * num_col;
        for (int i = 0; i < COLOR_SIZE; i++) {
            color[i] = color[i] / count;
        }
        return color;
    }

    private int who(double h, double s, double v) {
        Set<Integer> hw = dealH(h);
        Set<Integer> hs = dealS(s);
        Set<Integer> hv = dealV(v);

        Set<Integer> result = new HashSet<Integer>();
        result.clear();
        result.addAll(hw);
        result.retainAll(hs);
        result.retainAll(hv);

        Iterator<Integer> iterator = result.iterator();
        if (iterator.hasNext()) {
            return iterator.next();
        }
        return -1;
    }

    private Set<Integer> dealH(double h) {
        Set<Integer> who = new HashSet<Integer>();
        who.add(BLACK);
        who.add(GRAY);
        who.add(WHITE);
        if ((h >= 0 && h <= 10) || (h >= 156 && h <= 180)) {
            who.add(RED);
        } else if (h >= 11 && h <= 25) {
            who.add(ORANGE);
        } else if (h >= 26 && h <= 34) {
            who.add(YELLOW);
        } else if (h >= 35 && h <= 77) {
            who.add(GREEN);
        } else if (h >= 78 && h <= 99) {
            who.add(CYAN);
        } else if (h >= 100 && h <= 124) {
            who.add(BLUE);
        } else if (h >= 125 && h <= 155) {
            who.add(PURPLE);
        }
        return who;
    }

    private static Set<Integer> dealS(double s) {
        Set<Integer> who = new HashSet<Integer>();
        if (s >= 0 && s <= 43) {
            who.add(BLACK);
            who.add(GRAY);
            who.add(WHITE);
        } else if (s >= 44 && s <= 255) {
            who.add(RED);
            who.add(ORANGE);
            who.add(YELLOW);
            who.add(GREEN);
            who.add(CYAN);
            who.add(BLUE);
            who.add(PURPLE);
        }
        return who;
    }

    private static Set<Integer> dealV(double v) {
        Set<Integer> who = new HashSet<Integer>();
        if (v >= 0 && v <= 46) {
            who.add(BLACK);
        } else if (v >= 47 && v <= 255) {
            who.add(WHITE);
            who.add(RED);
            who.add(ORANGE);
            who.add(YELLOW);
            who.add(GREEN);
            who.add(CYAN);
            who.add(BLUE);
            who.add(PURPLE);
            if (v <= 220) {
                who.add(GRAY);
            }
        }
        return who;
    }

    public static String fd(double d) {
        NumberFormat nf = NumberFormat.getNumberInstance();
        // 保留两位小数
        nf.setMaximumFractionDigits(2);
        // 如果不需要四舍五入，可以使用RoundingMode.DOWN
        nf.setRoundingMode(RoundingMode.UP);
        return nf.format(d);
    }

    public static void main(String[] args) {
        String fileName = "H:\\changan\\2020-06-11-ImgColorAna\\testimgs\\IMG_0001.JPG";
        AnalyzeServer server = new AnalyzeServer();
        double[] color = server.analyze(fileName);
        for (int i = 0; i < COLOR_SIZE; i++) {
            String cv = fd(color[i] * 100) + "%";
            cv = "0%".equals(cv) ? "0" : cv;
            System.out.println(i + "=" + cv);
        }
    }

    public enum WhoColor {
        BLACK("黑色", 0, Color.BLACK),
        GRAY("灰色", 1, Color.GRAY),
        WHITE("白色", 2, Color.WHITE),
        RED("红色", 3, Color.RED),
        ORANGE("橙色", 4, Color.ORANGE),
        YELLOW("黄色", 5, Color.YELLOW),
        GREEN("绿色", 6, Color.GREEN),
        CYAN("青色", 7, Color.CYAN),
        BLUE("蓝色", 8, Color.BLUE);
        private int iv;
        private String in;
        private Color ic;

        WhoColor(String in, int iv, Color ic) {
            this.iv = iv;
            this.in = in;
            this.ic = ic;
        }

        public static WhoColor get(int iv) {
            for (WhoColor c : WhoColor.values()) {
                if (Objects.equals(iv, c.getIv())) {
                    return c;
                }
            }
            return null;
        }

        public String getIn() {
            return in;
        }

        public int getIv() {
            return iv;
        }

        public Color getIc() {
            return ic;
        }
    }
}